#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <kewinternal.h>

#define SOURCE_FILE_NAME "String"

#define value(OBJECT) ((char *)((OBJECT)->context[0]))
#define check_string(VAL) KewCheckType((VAL), &string_type, "string")
extern KewObjectType string_type;


METHOD(Hash)
{
  results[0] = KewNewInt(g_str_hash(value(receiver)));
}

METHOD(Equal)
{
  KewObject *other = KewSend0(args[0], "string");
  check_string(other);
  results[0] = KewNewBool(g_str_equal(value(receiver), value(other)));
}

METHOD(Concatenate)
{
  KewObject *other = KewSend0(args[0], "string");
  check_string(other);
  results[0] = KewWrapString(g_strconcat(value(receiver), value(other), NULL));
}

METHOD(Quote)
{
  KewObject *other = KewSend0(args[0], "string");
  check_string(other);
  results[0] = KewWrapString(g_strconcat(value(receiver), "\"", value(other), NULL));
}

METHOD(Apostrophe)
{
  KewObject *other = KewSend0(args[0], "string");
  check_string(other);
  results[0] = KewWrapString(g_strconcat(value(receiver), "'", value(other), NULL));
}

METHOD(Comma)
{
  KewObject *other = KewSend0(args[0], "string");
  check_string(other);
  results[0] = KewWrapString(g_strconcat(value(receiver), ",", value(other), NULL));
}

METHOD(Space)
{
  KewObject *other = KewSend0(args[0], "string");
  check_string(other);
  results[0] = KewWrapString(g_strconcat(value(receiver), " ", value(other), NULL));
}

METHOD(NewLine)
{
  results[0] = KewWrapString(g_strconcat(value(receiver), "\n", NULL));
}

METHOD(Size)
{
  results[0] = KewNewInt(strlen(value(receiver)));
}

METHOD(String)
{
  results[0] = receiver;
}

METHOD(Integer)
{
  /* FIXME: throw conversion exception if anything other than an int
     or out of range or is padded with spaces */
  results[0] = KewNewInt(strtol(value(receiver), NULL, 10));
}

METHOD(Real)
{
  /* FIXME: throw conversion exception if anything other than a real
     or out of range or is padded with spaces */
  results[0] = KewNewReal(strtod(value(receiver), NULL));
}

static void
Finalize(KewObject *receiver)
{
  g_free(value(receiver));
}

static KewObjectType string_type = {
  SOURCE_FILE_NAME, __LINE__,
  0,
  {
    {"=", Equal, 1, 1},
    {"hash", Hash, 0, 1},
    {",", Concatenate, 1, 1},
    {"quote", Quote, 1, 1},
    {"apostrophe", Apostrophe, 1, 1},
    {"space", Space, 1, 1},
    {"newLine", NewLine, 0, 1},
    {"newline", NewLine, 0, 1}, /* which spelling to go for? */
    {"comma", Comma, 1, 1},
    {"size", Size, 0, 1},
    {"string", String, 0, 1},
    {"integer", Integer, 0, 1},
    {"real", Real, 0, 1},
    {NULL, NULL, 0, 0}
  }
};


KewObject *
KewWrapString(char *s)
{
  KewObject *result = KewNewObject(&string_type);
  value(result) = s;
  return result;
}


KewObject *
KewNewString(char *s)
{
  return KewWrapString(g_strdup(s));
}


char *
KewStringVal(KewObject *object)
{
  check_string(object);
  return value(object);
}


KewObject *
KewWrapStringArray(char *strings[], unsigned number_of_strings)
{
  unsigned i;
  KewObject *wrapped_strings = KewList;

  for (i=0; i<number_of_strings; i++) {
    KewObject *wrapped_string = KewWrapString(strings[i]);
    wrapped_strings = KewSend1(wrapped_strings, "&", wrapped_string);
  }

  return wrapped_strings;
}
